import { Injectable } from '@angular/core';
import { Observable, Subject, timer } from 'rxjs';
import { delayWhen, retryWhen, tap } from 'rxjs/operators';
import { webSocket, WebSocketSubject } from 'rxjs/webSocket';

@Injectable({
    providedIn: 'root'
})
export class SocketService {
    socketLoginSubject: WebSocketSubject<any>;
    status: Subject<any> = new Subject<any>();
    constructor() {}

    /**
     * 连接
     */
    public connect(url: string): void {
        if (!this.socketLoginSubject || this.socketLoginSubject.closed) {
            this.socketLoginSubject = this.getNewWebsocket(url);
        }
    }

    private getNewWebsocket(url: string) {
        return webSocket({
            url,
            closeObserver: {
                next: () => {
                    this.socketLoginSubject = undefined;
                    this.connect(url);
                },
                error: (e) => {
                }
            },
        });
    }

    // 断线重连
    private reconnect(observable: Observable<any>): Observable<any> {
        // @ts-ignore
        return observable.pipe(retryWhen(errors => errors.pipe(tap(val => console.log('[Data Service] Try to reconnect', val)),
            delayWhen(_ => timer(3000)))));
    }
    /**
     * 发送消息
     */

    sendMessage(msg: any) {
        this.socketLoginSubject.next(msg);
    }

    /**
     * 接收消息
     * @param type 根据type获取信息
     * @param reconnect  是否断线重连,默认false
     */
    getMessage(type: string, reconnect: boolean = false): Observable<any> {

        const msg$ = this.socketLoginSubject.multiplex(
            () => ({ connect: type }),
            () => ({ close: type }),
            // @ts-ignore
            message => message.type === type
        ).pipe(
            reconnect ?
                this.reconnect : o => o
        );
        return msg$;
    }
    close() {
        this.socketLoginSubject.complete();
    }
}
